#pragma once
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>


#include "chat_session-odb.hxx"
#include "logger.hpp"

namespace im{
    class ChatSessionTable {
    public:
        typedef odb::query<ChatSession> query;
        typedef odb::result<ChatSession> result;
        using ptr = std::shared_ptr<ChatSessionTable>;
        ChatSessionTable(const std::shared_ptr<odb::database>& db)
                :_db(db){}
                
        // 新增会话
        bool insert(ChatSession& cs){
            try{
                odb::transaction t(_db->begin());
                _db->persist(cs);
                t.commit();
            } catch(const std::exception& e) {
                LOG_CRITICAL("新增会话失败 {}:{}！", cs.chat_session_name(),e.what());
                return false;
            }
            return true;
        }

        // 删除会话
        bool remove(const std::string& ssid){
            try{
                odb::transaction t(_db->begin());
                _db->erase_query<ChatSession>(query::chat_session_id == ssid);  // 删除会话
                _db->erase_query<ChatSessionMember>(odb::query<ChatSessionMember>::session_id == ssid); // 删除会话成员
                t.commit();
            } catch(const std::exception& e) {
                LOG_CRITICAL("删除会话失败 {}:{}！", ssid,e.what());
                return false;
            }
            return true;
        }
        // 删除会话
        bool remove(const std::string& user_id, const std::string& firend_id){
            std::string ssid;
            try{
                odb::transaction t(_db->begin());
                auto r(_db->query_one<SingleChatSession>(
                            odb::query<SingleChatSession>::csm1::user_id == user_id &&
                            odb::query<SingleChatSession>::csm2::user_id == firend_id &&
                            odb::query<SingleChatSession>::css::chat_session_type == ChatSessionType::SINGLE
                        ));
                ssid = r->chat_session_id;
                _db->erase_query<ChatSession>(query::chat_session_id == ssid);  // 删除会话
                _db->erase_query<ChatSessionMember>(odb::query<ChatSessionMember>::session_id == ssid); // 删除会话成员
                t.commit();
            } catch(const std::exception& e) {
                LOG_CRITICAL("删除会话失败 {}:{}！", ssid,e.what());
                return false;
            }
            return true;
        }

        // 获取会话信息
        std::shared_ptr<ChatSession> select(const std::string &ssid) {
            std::shared_ptr<ChatSession> res;
            try {
                odb::transaction trans(_db->begin());
                res.reset(_db->query_one<ChatSession>(query::chat_session_id == ssid));
                trans.commit();
            }catch (std::exception &e) {
                LOG_CRITICAL("通过会话ID获取会话信息失败 {}:{}！", ssid, e.what());
            }
            return res;
        }
        
        // 通过 好友ID 获取单聊会话的用户信息
        std::vector<SingleChatSession> singleChatSession(const std::string& uid){
            std::vector<SingleChatSession> res;
            try{
                odb::transaction t(_db->begin());
                typedef odb::query<SingleChatSession> query;
                typedef odb::result<SingleChatSession> result;
                result r(_db->query<SingleChatSession>(
                    query::css::chat_session_type == ChatSessionType::SINGLE &&
                    query::csm2::user_id != query::csm1::user_id &&
                    query::csm1::user_id == uid
                ));
                for(auto& i : r){
                    res.push_back(i);
                }
                t.commit();
            }catch (std::exception &e) {
                LOG_CRITICAL("获取用户 {} 的单聊会话失败:{}！", uid, e.what());
            }
            return res;
        }

        // 通过 好友ID 获取群聊会话信息
        std::vector<GroupChatSession> groupChatSession(const std::string& uid){
            std::vector<GroupChatSession> res;
            try{
                odb::transaction t(_db->begin());
                typedef odb::query<GroupChatSession> query;
                typedef odb::result<GroupChatSession> result;
                result r(_db->query<GroupChatSession>(
                    query::css::chat_session_type == ChatSessionType::GROUP &&
                    query::csm1::user_id == uid
                ));
                for(auto& i : r){
                    res.push_back(i);
                }
                t.commit();
            }catch (std::exception &e) {
                LOG_CRITICAL("获取用户 {} 的群聊会话失败:{}！", uid, e.what());
            }
            return res;
        }

    private:
        std::shared_ptr<odb::database> _db;
    };

}